home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Magazine / Backups / FBackNG / dirdiver.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-08-30  |  24.7 KB  |  875 lines

  1. // $VER: DirDiver 1.1.0
  2. // 
  3. // Purpose:     traverse a directory structure
  4. // History:     05-06-1998 Creation                      CDM 
  5. //              13-06-1998 Added BOOL icase switch       CDM 
  6. //              17-04-1999 Changed for FBackNG           CDM 
  7. //              24-04-1999 Added file functions          CDM 
  8. //              26-04-1999 Added time functions          CDM 
  9. //              30-04-1999 Added Handler, XPK            CDM 
  10. //              14-05-1999 Fixed dest. path creation     CDM 
  11. //                         MIRROR reports files in debug CDM 
  12. //              15-05-1999 MIRROR enabled                CDM 
  13. //                         Priority option               CDM 
  14. //              20-05-1999 MIRROR path creation fixed    CDM 
  15. //                         MIRROR check existenz only    CDM 
  16. //              30-10-1999 Added DirCleaner()            CDM 
  17. //              10-12-1999 Added noarch option           CDM
  18. //
  19. // (C)1999 Visionary Software - FREEWARE
  20.  
  21. #ifndef FBACKNG_H
  22. #include "fbackng.h"
  23. #endif
  24. #include "dirdiver.h"
  25. #include "support.h"
  26.  
  27. /* Xpk stuff */
  28. char errbuf[XPKERRMSGSIZE+1];
  29.  
  30. // log stuff
  31. char errormsg[256];
  32.  
  33. // Xpk func
  34. long __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
  35. {
  36.     sprintf(errormsg,"\r%4s: %-9s (%6d bytes, %3d%% done, %2d%% CF, %6d cps) ",
  37.         prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen, prog->xp_Done,
  38.         prog->xp_CF, prog->xp_Speed);
  39.     if(prog->xp_Type == XPKPROG_END)
  40.     {
  41.         strcat(errormsg,"\n");
  42.         check_write_log(NULL);
  43.     }     
  44.  
  45.     if(optval.val_verbose != OUT_QUIET)
  46.     {
  47.         if(prog->xp_Type == XPKPROG_END)
  48.         { 
  49.            printf("%s\n",errormsg);
  50.         }
  51.     }       
  52.   return 0;
  53. }
  54.  
  55. struct Hook chunkhook = {{0},chunkfunc};
  56.  
  57. struct TagItem tags[] = {
  58.    XPK_InName,    (long)NULL ,
  59.    XPK_OutName,   (long)NULL ,
  60.    XPK_Ignore,    (long)0    ,
  61.    XPK_NoClobber, (long)TRUE ,
  62.    XPK_GetError,  (long)errbuf,
  63.    XPK_ChunkHook, (long)&chunkhook,
  64.    TAG_DONE};
  65.  
  66. // check if user needs a log and write a message to it if active
  67. void check_write_log(char *custom)
  68. {
  69.     int err;
  70.     
  71.     if(optflg.opt_log)
  72.     {
  73.         if(custom!=NULL)
  74.                 sprintf(errormsg,"%s",custom);
  75.                 
  76.         if((err=put_LogOneMsg(optval.val_log,errormsg))!=DD_OK)
  77.         {
  78.                 fprintf(stderr,"%s: fatal: cannot write to log %s (%d)\n",optval.val_log,err);
  79.                 exit(1);
  80.         }
  81.     }
  82. }                
  83.  
  84. // check if directory exists
  85. int Check_Dir(char *name)
  86. {
  87.     DIR *dfd;
  88.     
  89.     dfd = opendir(name);
  90.     if(dfd == NULL)
  91.         return(FALSE);
  92.     closedir(dfd);
  93.     
  94.     return(TRUE);
  95. }
  96.  
  97. // check if file exists and is readable
  98. int Check_File(char *name)
  99. {
  100.     if((access(name,F_OK))==0)
  101.        return(TRUE);
  102.  
  103.     return(FALSE);
  104. }
  105.  
  106. int Copy_File(char *infile,char *outfile)
  107. {
  108.     FILE *in,*out;
  109.     char *buf;
  110.     int i;
  111.     
  112.     if((buf=malloc(BUF_SIZE))==NULL)
  113.         return(DD_CALLOC);
  114.  
  115.     if((in=fopen(infile,"r"))==NULL)
  116.     {
  117.         free(buf);
  118.         return(DD_OPENSOURCE);
  119.     }
  120.  
  121.     if((out=fopen(outfile,"wt"))==NULL)
  122.     {
  123.         fclose(in);
  124.         free(buf);
  125.         return(DD_OPENDEST);
  126.     }
  127.     
  128.     while(i=fread(buf,1,BUF_SIZE,in))
  129.         if(fwrite(buf,1,i,out)!=i)
  130.                 break;
  131.                 
  132.     i=(ferror(in)||ferror(out))?DD_COPY:DD_OK;
  133.     
  134.     fclose(in);
  135.     fclose(out);
  136.     free(buf);
  137.     
  138.     return(i);            
  139. }
  140.  
  141. // checks dest dir and clones creation of path
  142. int Clone_Dir(char *path)
  143. {
  144.     int op,np;
  145.     char res[512],target[512];
  146.  
  147.     res[0]=0;
  148.     
  149.     np = SplitName(path,':',res,0,512);
  150.     
  151.     if(np!=-1)
  152.     {
  153.         strcat(res,":");
  154.         if(!(Check_Dir(res)))
  155.                 return(DD_VOLERROR);
  156.     }
  157.     else
  158.         np = 0;
  159.     
  160.     strcpy(target,res);
  161.  
  162.     op = np;
  163.     while(op!=-1)
  164.     {
  165.         np = SplitName(path,'/',res,op,512);
  166.  
  167.         sprintf(target,"%s%s",target,res);
  168.         if(!(Check_Dir(target)))
  169.                 mkdir(target);
  170.             
  171.         if(np!=-1)
  172.                 strcat(target,"/");
  173.         op = np;
  174.     }            
  175.  
  176.     return(DD_OK);                
  177. }
  178.  
  179. // checks paths
  180. void Check_Slash(char *path)
  181. {
  182.     char *p,*q;
  183.     int found,i;
  184.     char res[512];
  185.     
  186.     found = 0;
  187.     p = path;
  188.     q = NULL;
  189.     
  190.     for(i=0;*p != 0; q=p,p++)
  191.     {
  192.         if(*p == '/')
  193.         {
  194.                 found++;
  195.                 if(*q==':')
  196.                         found = 2;
  197.         }
  198.         else
  199.                 found = 0;        
  200.                 
  201.         if(found<2)
  202.         {
  203.                 res[i] = *p;
  204.                 i++;
  205.         }
  206.         else
  207.                 found=0;
  208.     }               
  209.     res[i]=0;             
  210.     strcpy(path,res);
  211. }
  212.                 
  213. // adds delete flag of file
  214. int Set_Delete_File(char *name)
  215. {
  216.     int error;
  217.     
  218.     error = DD_OK;
  219.     
  220.     chmod(name,S_IREAD|S_IWRITE|S_IDELETE);  
  221.     return(error);
  222. }    
  223.  
  224. // adds archive flag of file
  225. int Set_Archive_File(char *name)
  226. {
  227.     BPTR lock;
  228.     struct FileInfoBlock fib;
  229.     int error;
  230.     
  231.     error = DD_OK;
  232.     
  233.     if((lock=Lock(name,ACCESS_READ))==NULL)
  234.        return(DD_LOCKFILE);
  235.     
  236.     if((Examine(lock,&fib)))
  237.     {
  238.         UnLock(lock);
  239.         fib.fib_Protection |= FIBF_ARCHIVE;
  240.         if(!(SetProtection((STRPTR)name,fib.fib_Protection)))
  241.                 error = DD_ARCHFILE;
  242.     }    
  243.     else
  244.     {
  245.         UnLock(lock);
  246.         error = DD_EXFILE;
  247.     }  
  248.     return(error);
  249. }
  250.  
  251. // clones flags of file
  252. int Clone_Protect_File(char *name, char *uit)
  253. {
  254.     BPTR lock;
  255.     struct FileInfoBlock fib;
  256.     int error;
  257.     
  258.     error = DD_OK;
  259.     
  260.     if((lock=Lock(name,ACCESS_READ))==NULL)
  261.        return(DD_LOCKFILE);
  262.     
  263.     if((Examine(lock,&fib)))
  264.     {
  265.         UnLock(lock);
  266.         if(!(SetProtection((STRPTR)uit,fib.fib_Protection)))
  267.                 error = DD_PROTFILE;
  268.     }    
  269.     else
  270.     {
  271.         UnLock(lock);
  272.         error = DD_EXFILE;
  273.     }  
  274.     return(error);
  275. }
  276.  
  277. // clone date to destination file
  278. int Clone_DateStamp_File(char *name, char *uit)
  279. {
  280.     BPTR lock;
  281.     struct FileInfoBlock fib;
  282.     int error;
  283.     
  284.     error = DD_OK;
  285.     
  286.     if((lock=Lock(name,ACCESS_READ))==NULL)
  287.        return(DD_LOCKFILE);
  288.     
  289.     if((Examine(lock,&fib)))
  290.     {
  291.         UnLock(lock);
  292.         if(!(SetFileDate((STRPTR)uit,&fib.fib_Date)))
  293.                 error = DD_DATEFILE;
  294.     }    
  295.     else
  296.     {
  297.         UnLock(lock);
  298.         error = DD_EXFILE;
  299.     }    
  300.     return(error);
  301. }
  302.  
  303. int System_DateStamp_File(char *name)
  304. {
  305.     struct DateStamp *tijd;
  306.     int error;
  307.     
  308.     error = DD_OK;
  309.     
  310.     tijd = __timecvt(time(NULL));
  311.     
  312.     if(!(SetFileDate((STRPTR)name,tijd)))
  313.                 error = DD_SYSTFILE;
  314.  
  315.     return(error);
  316. }
  317.  
  318. // clone comment to destination file
  319. int Clone_Comment_File(char *name, char *uit)
  320. {
  321.     BPTR lock;
  322.     struct FileInfoBlock fib;
  323.     int error;
  324.     
  325.     error = DD_OK;
  326.     
  327.     if((lock=Lock(name,ACCESS_READ))==NULL)
  328.        return(DD_LOCKFILE);
  329.        
  330.     if((Examine(lock,&fib)))
  331.     {
  332.         UnLock(lock);
  333.         if(!(SetComment((STRPTR)uit,(STRPTR)&fib.fib_Comment)))
  334.                   error = DD_COMMFILE;
  335.     }    
  336.     else
  337.     {
  338.         UnLock(lock);
  339.         error = DD_EXFILE;
  340.     }    
  341.     return(error);
  342. }
  343.  
  344. // delete a file
  345. int Delete_File(char *thefile)
  346. {
  347.     int error;
  348.     
  349.     if((error=Set_Delete_File(thefile))!=DD_OK)
  350.         return(error);
  351.         
  352.     if((error=remove(thefile))!=0)
  353.         return(DD_DELFILE);
  354.  
  355.     return(DD_OK);
  356. }
  357.  
  358. // delete a dir
  359. int Delete_Dir(char *thedir)
  360. {
  361.     int error;
  362.     
  363.     if((error=rmdir(thedir))!=0)
  364.         return(DD_DELDIRS);
  365.  
  366.     return(DD_OK);
  367. }
  368.  
  369. // pack a file
  370. int Pack_File(char *in,char *out,char *packer)
  371. {
  372.     int res;
  373.  
  374.     tags[0].ti_Data = (long)in;
  375.     tags[1].ti_Data = (long)out;
  376.     tags[2].ti_Tag = XPK_PackMethod;
  377.     tags[2].ti_Data = (long)packer;
  378.     res = XpkPack(tags);
  379.     
  380.     return(res);
  381. }
  382.  
  383. // get flags and convert to displayable string
  384. void WhichFlags(ULONG flg,char *res)
  385. {
  386.     char temp[6];
  387.     
  388.     if((flg&FIBF_ARCHIVE)==0)
  389.         temp[0] = '-';
  390.     else
  391.         temp[0] = 'a';
  392.         
  393.     if((flg&FIBF_READ)!=0)
  394.         temp[1] = '-';
  395.     else
  396.         temp[1] = 'r';
  397.         
  398.     if((flg&FIBF_WRITE)!=0)
  399.         temp[2] = '-';
  400.     else
  401.         temp[2] = 'w';
  402.         
  403.     if((flg&FIBF_EXECUTE)!=0)
  404.         temp[3] = '-';
  405.     else
  406.         temp[3] = 'e';
  407.         
  408.     if((flg&FIBF_DELETE)!=0)
  409.         temp[4] = '-';
  410.     else
  411.         temp[4] = 'd';
  412.         
  413.     temp[5] = 0;
  414.     
  415.     strcpy(res,temp);        
  416. }
  417.  
  418. BOOL Compare_Dates(STRPTR name)
  419. {
  420.     BPTR lock;
  421.     LONG r;
  422.     struct FileInfoBlock fib;
  423.     
  424.     if((lock=Lock(name,ACCESS_READ))==NULL)
  425.        return(FALSE);
  426.     if((Examine(lock,&fib)))
  427.     {
  428.         UnLock(lock);
  429.         if(optflg.opt_before)
  430.         {
  431.            r = CompareDates(&dt_Before.dat_Stamp,&fib.fib_Date);
  432.            if(r>0)
  433.              return(FALSE);
  434.            else
  435.              return(TRUE);  
  436.         }
  437.         if(optflg.opt_after)
  438.         {
  439.            r = CompareDates(&dt_After.dat_Stamp,&fib.fib_Date);
  440.            if(r>0)
  441.              return(TRUE);
  442.            else
  443.              return(FALSE);  
  444.         }   
  445.      }    
  446.     else
  447.     {
  448.         UnLock(lock);
  449.         return(FALSE);
  450.     }    
  451.     return(FALSE);
  452. }
  453.     
  454. int Handle_Backup_File(char *infile,char *outfile)
  455. {
  456.     int error;
  457.     
  458.     if(Check_File(outfile))
  459.     {
  460.            error = Delete_File(outfile);
  461.            if(error!=DD_OK)
  462.                 return(error);
  463.     }
  464.  
  465.     if(optflg.opt_compress)
  466.     {
  467.         error=Pack_File(infile,outfile,optval.val_compress);
  468.         
  469.         if(error!=0) // if error pack, then just copy
  470.                 error=Copy_File(infile,outfile);
  471.     }
  472.     else
  473.         error=Copy_File(infile,outfile);
  474.         
  475.     if(error==DD_OK)
  476.     {
  477.         if((error=Clone_Protect_File(infile,outfile))==DD_OK)
  478.         {
  479.             if(optflg.opt_noarch) // V1.2.0
  480.                 error = DD_OK;
  481.             else
  482.                 error=Set_Archive_File(infile);
  483.  
  484.             if(error != DD_OK)
  485.             {
  486.                 if(!optflg.opt_nonotes)
  487.                 {
  488.                     if((error=Clone_Comment_File(infile,outfile))==DD_OK)
  489.                     {
  490.                         if(optflg.opt_touch)
  491.                             error=System_DateStamp_File(outfile);
  492.                         else
  493.                             error=Clone_DateStamp_File(infile,outfile);
  494.                     }
  495.                 }
  496.             }
  497.         }                    
  498.     }
  499.     
  500.     return(error);
  501. }
  502.  
  503. int Handle_Mirror_File(char *infile,char *outfile)
  504. {
  505.     int error=DD_OK;
  506.     
  507.     if(!(Check_File(outfile)))
  508.     {
  509.            error = Delete_File(infile);
  510.            if(error!=DD_OK)
  511.                 return(error);
  512.            prc_files++;
  513.            return(DD_DELETED);     
  514.     }
  515.  
  516.     return(error);
  517. }
  518.          
  519. // backup/mirror engine
  520. int __aligned __saveds DirDiver(char *root,int mode)
  521. {
  522.     BOOL                more;
  523.     BOOL                valid;
  524.     BPTR                lock;
  525.     struct ExAllControl *eac;
  526.     struct ExAllData    *ead;
  527.     struct ExAllData    *tmp;
  528.     UBYTE               templat[256];
  529.     UBYTE               sname[512],dname[512],tname[512],tdir[512];
  530.     char                flags[6];
  531.     int                 result;
  532.  
  533.     if(!(lock = Lock(root, ACCESS_READ))) return(DD_LOCK); // get lock on FS
  534.  
  535.     if(!(tmp = calloc(1,4096)))
  536.     {
  537.         UnLock(lock);
  538.         return(DD_CALLOC);
  539.     }
  540.     
  541.     ParsePatternNoCase(optval.val_pattern, &templat[0], 256);
  542.         
  543.     if(!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  544.     {
  545.         free(tmp);
  546.         UnLock(lock);
  547.         return(DD_ALLOCDOS);
  548.     }
  549.  
  550.     sprintf(errormsg,"[Searching Directory     ]   %s\n",root);
  551.     check_write_log(NULL);
  552.     if(optval.val_verbose > OUT_NORMAL)
  553.     {
  554.         printf("%s",errormsg);
  555.     }    
  556.     
  557.     eac->eac_LastKey = 0;
  558.     
  559.     tot_direc++;
  560.     
  561.     // get files
  562.     do {
  563.         Chk_Abort();
  564.         
  565.         more = ExAll(lock, tmp, 4096, ED_COMMENT, eac);
  566.         
  567.         if(eac->eac_Entries != 0)
  568.         {
  569.                 ead = tmp;
  570.  
  571.                 if(mode == BACKUP_PHASE)
  572.                 {
  573.                         if((strcmp(root,optval.val_source))!=0)
  574.                                 strmid(root,tname,strlen(optval.val_source)+1,strlen(root));
  575.                         else
  576.                                 strcpy(tname,"");
  577.                 }
  578.                 else // MIRROR_PHASE
  579.                 {
  580.                         if((strcmp(root,optval.val_dest))!=0)
  581.                                 strmid(root,tname,strlen(optval.val_dest)+1,strlen(root));
  582.                         else
  583.                                 strcpy(tname,"");
  584.                 }
  585.                                                              
  586.         
  587.                 if(optval.val_verbose == OUT_DEBUG)
  588.                 {
  589.                         sprintf(errormsg,"[Found Directory Entries ]   %ld\n",eac->eac_Entries);
  590.                         check_write_log(NULL);
  591.                         printf("%s",errormsg);
  592.                 }
  593.         
  594.                 do {
  595.                 Chk_Abort();
  596.             
  597.                 if(ead->ed_Type < 0) // a file
  598.                 {
  599.   
  600.                         tot_files++;
  601.                               
  602.                         if((MatchPatternNoCase(&templat[0], ead->ed_Name)))
  603.                         {
  604.                                 strcpy(sname,root);
  605.                                 AddPart(sname,ead->ed_Name,512);
  606.  
  607.                       
  608.                                 if(mode == BACKUP_PHASE)
  609.                                 {
  610.  
  611.                                         WhichFlags(ead->ed_Prot,flags);
  612.                         
  613.                                         if(optval.val_verbose == OUT_DEBUG)
  614.                                         {
  615.                                                 sprintf(errormsg,"[Protection Flags        ]   %s\n",flags);
  616.                                                 check_write_log(NULL);
  617.                                                 printf("%s",errormsg);
  618.                                         }
  619.  
  620.                                         sprintf(errormsg,"[Matched Filename        ]   %s\n",sname);
  621.                                         check_write_log(NULL);                                
  622.                                         if(optval.val_verbose > OUT_NORMAL)
  623.                                         {
  624.                                                 printf("%s",errormsg);
  625.                                         }
  626.  
  627.  
  628.                                         if((flags[0]=='a' && optflg.opt_every)||flags[0]=='-')
  629.                                         {
  630.                                                 if(optflg.opt_before || optflg.opt_after)
  631.                                                         valid = Compare_Dates(sname);
  632.                                                 else
  633.                                                         valid = TRUE;
  634.                                                                 
  635.                                                 if(valid)
  636.                                                 {
  637.                                                         prc_files++;
  638.  
  639.                                                         sprintf(errormsg,"[Backup Filename         ]   %s\n",sname);
  640.                                                         check_write_log(NULL);
  641.                                                         if(optval.val_verbose > OUT_QUIET)
  642.                                                                 printf("%s",errormsg);
  643.  
  644.                                                         strcpy(dname,optval.val_dest); // dest root
  645.                                                         AddPart(dname,tname,512); // dest path
  646.                                                         Check_Slash(dname);
  647.                                                         strcpy(tdir,dname); // save dest path
  648.                                                 
  649.                                                         AddPart(dname,ead->ed_Name,512); // dest file
  650.                                                 
  651.                                                         if(optval.val_verbose == OUT_DEBUG)
  652.                                                         {
  653.                                                                 sprintf(errormsg,"[Source, Destination     ]   %s, %s\n",sname,dname);                                        
  654.                                                                 check_write_log(NULL);    
  655.                                                                 printf("%s",errormsg);                                        
  656.                                                         }
  657.  
  658.                                                         if(!optflg.opt_simulate)
  659.                                                         {                                        
  660.                                                                 if((result = Clone_Dir(tdir))!=DD_OK)
  661.                                                                 {
  662.                                                                         FreeDosObject(DOS_EXALLCONTROL, eac);
  663.                                                                         free(tmp);
  664.                                                                         UnLock(lock);
  665.                                                                        return(result);
  666.                                                                 }
  667.                                             
  668.                                                                 if((result = Handle_Backup_File(sname,dname))!=DD_OK)
  669.                                                                 {
  670.                                                                         FreeDosObject(DOS_EXALLCONTROL, eac);
  671.                                                                         free(tmp);
  672.                                                                         UnLock(lock);
  673.                                                                         return(result);
  674.                                                                 }  
  675.                                                         }
  676.                                                 }            
  677.                                         }                                        
  678.                                 }
  679.                                 else // MIRROR PHASE
  680.                                 {
  681.  
  682.                                         strcpy(dname,optval.val_source); // dest root
  683.                                         AddPart(dname,tname,512); // dest path
  684.                                         Check_Slash(dname);
  685.                                         strcpy(tdir,dname); // save dest path
  686.                                                 
  687.                                         AddPart(dname,ead->ed_Name,512); // dest file
  688.  
  689.                                         if(optval.val_verbose == OUT_DEBUG)
  690.                                         {
  691.                                                 sprintf(errormsg,"[Source, Destination     ]   %s, %s\n",sname,dname);                                        
  692.                                                 check_write_log(NULL);    
  693.                                                 printf("%s",errormsg);                                        
  694.                                         }
  695.  
  696.                                         if(!optflg.opt_simulate)
  697.                                         {                                        
  698.                                                 if((result = Handle_Mirror_File(sname,dname))!=DD_OK)
  699.                                                 {
  700.                                                     if(result != DD_DELETED)
  701.                                                     {
  702.                                                         FreeDosObject(DOS_EXALLCONTROL, eac);
  703.                                                         free(tmp);
  704.                                                         UnLock(lock);
  705.                                                         return(result);
  706.                                                     }    
  707.                                                 }    
  708.                                                 if(result == DD_DELETED)
  709.                                                 {
  710.                                                         sprintf(errormsg,"[Delete Filename         ]   %s\n",sname);
  711.                                                         check_write_log(NULL);
  712.                                                         if(optval.val_verbose > OUT_QUIET)
  713.                                                         {
  714.                                                                 printf("%s",errormsg);
  715.                                                         }        
  716.                                                 }
  717.                                         } 
  718.                                 }    
  719.                         }        
  720.                 }
  721.             
  722.             ead = ead->ed_Next;
  723.             } while(ead);
  724.         }    
  725.     } while(more);
  726.     
  727.     more = FALSE;
  728.     
  729.     eac->eac_LastKey = 0;
  730.     
  731.     if(optflg.opt_recursive)
  732.     {
  733.         // get directories
  734.         do {
  735.                 Chk_Abort();
  736.         
  737.                 more = ExAll(lock, tmp, 4096, ED_SIZE, eac);
  738.         
  739.                 if(eac->eac_Entries == 0) continue;
  740.         
  741.                 ead = tmp;
  742.         
  743.                 do {
  744.                         Chk_Abort();
  745.             
  746.                         if(ead->ed_Type > 0) // a directory
  747.                         {
  748.                                 strcpy(sname, root);
  749.                                 AddPart(sname, ead->ed_Name, 512);
  750.                 
  751.                                 result = DirDiver(sname,mode);
  752.                 
  753.                                 if(result!=DD_OK)
  754.                                 {
  755.                                         if(eac)  FreeDosObject(DOS_EXALLCONTROL, eac);
  756.                                         if(tmp)  free(tmp);
  757.                                         if(lock) UnLock(lock);
  758.                                         return(result);
  759.                                 }
  760.                         }
  761.             
  762.                          ead = ead->ed_Next;
  763.                 } while(ead);
  764.         } while(more);
  765.     }
  766.     
  767.     // clean up
  768.     if(eac)   FreeDosObject(DOS_EXALLCONTROL, eac);
  769.     if(tmp)   free(tmp);
  770.     if(lock)  UnLock(lock);
  771.     
  772.     return(DD_OK);
  773. }
  774.  
  775. // cleaner engine
  776. int __aligned __saveds DirCleaner(char *root)
  777. {
  778.     BOOL                more;
  779.     BOOL                empty;
  780.     BPTR                lock;
  781.     struct ExAllControl *eac;
  782.     struct ExAllData    *ead;
  783.     struct ExAllData    *tmp;
  784.     UBYTE               sname[512];
  785.     int                 result;
  786.  
  787.     if(!(lock = Lock(root, ACCESS_READ))) return(DD_LOCK); // get lock on FS
  788.  
  789.     if(!(tmp = calloc(1,4096)))
  790.     {
  791.         UnLock(lock);
  792.         return(DD_CALLOC);
  793.     }
  794.     
  795.     if(!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  796.     {
  797.         free(tmp);
  798.         UnLock(lock);
  799.         return(DD_ALLOCDOS);
  800.     }
  801.  
  802.     sprintf(errormsg,"[Searching Directory     ]   %s\n",root);
  803.     check_write_log(NULL);
  804.     if(optval.val_verbose > OUT_NORMAL)
  805.     {
  806.         printf("%s",errormsg);
  807.     }    
  808.     
  809.     eac->eac_LastKey = 0;
  810.     empty = FALSE;
  811.     tot_direc++;
  812.     more = FALSE;
  813.         
  814.     if(optflg.opt_recursive)
  815.     {
  816.         // get directories
  817.         do {
  818.                 Chk_Abort();
  819.         
  820.                 more = ExAll(lock, tmp, 4096, ED_SIZE, eac);
  821.         
  822.                 if(eac->eac_Entries == 0) 
  823.                 {
  824.                     empty = TRUE;
  825.                     continue;
  826.                 }
  827.                 
  828.                 ead = tmp;
  829.         
  830.                 do {
  831.                         Chk_Abort();
  832.             
  833.                         if(ead->ed_Type > 0) // a directory
  834.                         {
  835.                                 strcpy(sname, root);
  836.                                 AddPart(sname, ead->ed_Name, 512);
  837.                 
  838.                                 result = DirCleaner(sname);
  839.                 
  840.                                 if(result!=DD_OK)
  841.                                 {
  842.                                         if(eac)  FreeDosObject(DOS_EXALLCONTROL, eac);
  843.                                         if(tmp)  free(tmp);
  844.                                         if(lock) UnLock(lock);
  845.                                         return(result);
  846.                                 }
  847.                         }
  848.             
  849.                          ead = ead->ed_Next;
  850.                 } while(ead);
  851.         } while(more);
  852.     }
  853.     
  854.     // clean up
  855.     if(eac)   FreeDosObject(DOS_EXALLCONTROL, eac);
  856.     if(tmp)   free(tmp);
  857.     if(lock)  UnLock(lock);
  858.     
  859.     if(empty)
  860.     {
  861.         result = Delete_Dir(root);
  862.         if(result!=DD_OK)
  863.               return(result);
  864.         del_dirs++;
  865.         sprintf(errormsg,"[Deleted Directory     ]   %s\n",root);
  866.         check_write_log(NULL);
  867.         if(optval.val_verbose > OUT_NORMAL)
  868.         {
  869.                 printf("%s",errormsg);
  870.         }    
  871.     }    
  872.     return(DD_OK);
  873. }
  874. // end
  875.